﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Xml.Serialization;
using Demonstartor.FlightAnalysisXSD;

namespace Demonstartor
{
    class FligthAbnoramalityReader
    {
        Flight Flight;
        flightAnalysis FlightAnalysis;
        AdditionalData AdditionalData;
        RusParamsReader RusParamsReader;

        public FligthAbnoramalityReader()
        {

        }

        public void LoadAnalysis(string XMLName, int Offset)
        {
            XmlSerializer XS = new XmlSerializer(typeof(flightAnalysis));
            FileStream FS = new FileStream(XMLName, FileMode.Open);
            FlightAnalysis = (flightAnalysis)XS.Deserialize(FS);
            FS.Close();

            RusParamsReader = new Demonstartor.RusParamsReader();

            AdditionalData = new Demonstartor.AdditionalData(XMLName.Replace(".xml", ".txt"));


            Flight = new Flight(AdditionalData.FlightXMLPath, Offset, AdditionalData.AdditionalTime, AdditionalData.FlightRKXMLPath);

            int PCount = Flight.ParameterCount;
            for (int i = 0; i < PCount; i++)
            {
                string CurName = Flight.ParameterNames[i];
                if (CurName.IndexOf("param") == 0)
                {
                    string ShortName, Description;
                    if (RusParamsReader.Resolve(CurName, out ShortName, out Description))
                    {
                        Flight.ParameterNames[i] = ShortName;
                        Flight.ParameterDescriptions[i] = Description;
                    }
                }

            }
        }

        public FlightAbnormalitiesList GetAllAbnormalities()
        {
            abnormality[] Abnormalities = FlightAnalysis.studies[0].abnormalities;

            FlightAbnormalitiesList FAL = new FlightAbnormalitiesList();

            int ACount = Abnormalities.Count();

            for (int i = 0; i < ACount; i++)
            {
                FlightAbnormality FA = new FlightAbnormality(Abnormalities[i].name,
                    Abnormalities[i].description, Abnormalities[i].startDateTime, Abnormalities[i].stopDateTime);
                FAL.Add(FA);
            }

            return FAL;
        }

        public InvolvedParametersList GetAllParams()
        {
            InvolvedParametersList Res = new InvolvedParametersList();
            int PCount = Flight.ParameterCount;
            for (int i = 0; i < PCount; i++)
            {
                string Name = Flight.ParameterNames[i];
                string Description = Flight.ParameterDescriptions[i];
                Res.Add(new InvolvedParameter(Name, Description, ""));

            }

            return Res;
        }

        public int GetAbnormalityIndex(DateTime DateTime)
        {
            int ACount = FlightAnalysis.studies[0].abnormalities.Count();


            for (int AbnormalityIndex = 0; AbnormalityIndex < ACount; AbnormalityIndex++)
            {
                abnormality Abnormality = FlightAnalysis.studies[0].abnormalities[AbnormalityIndex];

                if ((DateTime >= Abnormality.startDateTime) && (DateTime <= Abnormality.stopDateTime))
                    return AbnormalityIndex;

            }
            return -1;
        }

        public InvolvedParametersList GetAllInvolvedParams(int AbnormalityIndex, bool AddDensity = false, bool AddBorderLine = false)
        {
            abnormality Abnormality = FlightAnalysis.studies[0].abnormalities[AbnormalityIndex];

            int PCount = Abnormality.involvedParameters.Count();

            InvolvedParametersList IPL = new InvolvedParametersList();

            for (int i = 0; i < PCount; i++)
            {
                InvolvedParameter IP = new InvolvedParameter(Abnormality.involvedParameters[i].name,
                    Abnormality.involvedParameters[i].description, Abnormality.involvedParameters[i].reason);

                if (IP.Name.IndexOf("param") == 0)
                {
                    string ShortName, Description;
                    if (RusParamsReader.Resolve(IP.Name, out ShortName, out Description))
                    {
                        IP.Name = ShortName;
                        IP.Description = Description;
                    }
                }

                if (IP.Description == null)
                {
                    int Ind = Flight.ParameterNames.IndexOf(IP.Name);
                    if (Ind != -1)
                        IP.Description = Flight.ParameterDescriptions[Ind];
                    else
                        IP.Description = IP.Name;
                }

                IPL.Add(IP);
            }

            if (AddDensity)
                IPL.Add(InvolvedParameter.Density());

            if (AddBorderLine)
                IPL.Add(InvolvedParameter.BorderLine());
            

            return IPL;
        }

        public InvolvedParametersList GetAllInvolvedParams()
        {
            int ACount = FlightAnalysis.studies[0].abnormalities.Count();

            InvolvedParametersList InvolvedParams = new InvolvedParametersList();

            for (int AbnormalityIndex = 0; AbnormalityIndex < ACount; AbnormalityIndex++)
            {
                abnormality Abnormality = FlightAnalysis.studies[0].abnormalities[AbnormalityIndex];

                int PCount = Abnormality.involvedParameters.Count();
                for (int i = 0; i < PCount; i++)
                {
                    InvolvedParameter IP = new InvolvedParameter(Abnormality.involvedParameters[i].name,
                        Abnormality.involvedParameters[i].description, Abnormality.involvedParameters[i].reason);
                    if (InvolvedParams.IndexOf(IP) == -1)
                    {
                        InvolvedParams.Add(IP);

                        if (IP.Name.IndexOf("param") == 0)
                        {
                            string ShortName, Description;
                            if (RusParamsReader.Resolve(IP.Name, out ShortName, out Description))
                            {
                                IP.Name = ShortName;
                                IP.Description = Description;
                            }
                        }

                        if (IP.Description == null)
                        {
                            int Ind = Flight.ParameterNames.IndexOf(IP.Name);
                            if (Ind != -1)
                                IP.Description = Flight.ParameterDescriptions[Ind];
                            else
                                IP.Description = IP.Name;
                        }
                    }
                }
            }

            InvolvedParams.Add(InvolvedParameter.Density());
            InvolvedParams.Add(InvolvedParameter.BorderLine());

            return InvolvedParams;
        }

        public FlightValues GetFlightValues(DateTime StartDateTime, DateTime EndDateTime, InvolvedParametersList Parameters)
        {
            // First. Getting parameters names
            string[] ParametersNames = Parameters.GetNames(false);
            bool HasDensity = Parameters.HasDensity();
            bool HasBorderLine = Parameters.HasBorderLine();

            // Second. Getting parameter values
            Dictionary<string, double[]> Vals = Flight.GetParameters(ParametersNames, StartDateTime, EndDateTime);
            if (HasDensity)
                Vals.Add("Оценка", 
                    AdditionalData.GetDensity(Flight.DateTimeToFlightInd(StartDateTime) * 4, Flight.DateTimeToFlightInd(EndDateTime) * 4));
            
            if (HasBorderLine)
                Vals.Add("Граница",
                    AdditionalData.GetBorderLine(Flight.DateTimeToFlightInd(StartDateTime) * 4, Flight.DateTimeToFlightInd(EndDateTime) * 4));
    

            // Third
            FlightValues Res = new FlightValues();
            int PCount = Parameters.Count;
            for (int i = 0; i < PCount; i++)
            {
                InvolvedParameter Cur = Parameters[i];
                double[] PVals = Vals[Cur.Name];
                int VCount = PVals.Count();

                if (Cur.Sin)
                {
                    
                    for (int j = 0; j < VCount; j++)
                        PVals[j] = Math.Sin(PVals[j]);
                } else if (Cur.Cos)
                {
                    for (int j = 0; j < VCount; j++)
                        PVals[j] = Math.Cos(PVals[j]);
                }

                Res.Add(Cur, new DateTimeValues(StartDateTime, EndDateTime, 4, PVals));
            }

            return Res;
        }

        public FlightValues GetFlightValues(int AbnormalityIndex, int AdditionalTime, InvolvedParametersList AdditionalParameters)
        {
            // Get abnormality, get it's parameters
            InvolvedParametersList MainParams = new InvolvedParametersList();
            MainParams.AddRange(AdditionalParameters);

            abnormality Abnorm = FlightAnalysis.studies[0].abnormalities[AbnormalityIndex];

            DateTime StartAbnormDateTime = Abnorm.startDateTime;
            DateTime EndAbnormDateTime = Abnorm.stopDateTime;

            if (EndAbnormDateTime == StartAbnormDateTime)
            {
                StartAbnormDateTime = StartAbnormDateTime.AddSeconds(1);
                EndAbnormDateTime = EndAbnormDateTime.AddSeconds(1);
            }

            DateTime StartDateTime = StartAbnormDateTime.AddSeconds(-AdditionalTime);
            if (StartDateTime - Flight.TimeOffset < Flight.StartTime - Flight.TimeOffset)
                StartDateTime = Flight.StartTime + Flight.TimeOffset;
            
            DateTime EndDateTime = EndAbnormDateTime.AddSeconds(AdditionalTime);
            if (EndDateTime - Flight.TimeOffset > Flight.EndTime)
                EndDateTime = Flight.EndTime + Flight.TimeOffset;

            FlightValues FV =  GetFlightValues(StartDateTime, EndDateTime, MainParams);
            FV.Split(StartAbnormDateTime);
            FV.Split(EndAbnormDateTime);

            return FV;

        }

        
        public FlightValues GetFlightValues(InvolvedParametersList Parameters)
        {
            // Get abnormality, get it's parameters1

            int ACount = FlightAnalysis.studies[0].abnormalities.Count();

            FlightValues FV = GetFlightValues(FlightAnalysis.flightInformation.startDateTime, FlightAnalysis.flightInformation.stopDateTime, Parameters);

            for (int i = 0; i < ACount; i++)
            {
                abnormality Abnorm = FlightAnalysis.studies[0].abnormalities[i];

                DateTime StartAbnormDateTime = Abnorm.startDateTime;
                DateTime EndAbnormDateTime = Abnorm.stopDateTime;

                if (EndAbnormDateTime == StartAbnormDateTime)
                {
                    StartAbnormDateTime = StartAbnormDateTime.AddSeconds(-1);
                    EndAbnormDateTime = EndAbnormDateTime.AddSeconds(1);
                }
                                
                FV.Split(StartAbnormDateTime);
                FV.Split(EndAbnormDateTime);
            }

            return FV;

        }

    }
}
